//  logger.c
//  Progetto Ingegneria del Web
//
//  Created by Andrea Vitale on 16/10/12.
//  Copyright (c) 2012 Andrea Vitale. All rights reserved.

#include "logger.h"
#include "config_manager.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>

void initLogger() {
    fprintf(stderr, "Initializing logger..\n");
    
    logger = malloc(sizeof(logger_t));
    
    logger->current_error_level = malloc(strlen(config_manager->log_level)*sizeof(char));
    logger->log_verbose_path = malloc(strlen(config_manager->log_verbose_path)*sizeof(char));
    logger->log_verbose_filename = malloc(strlen(config_manager->log_verbose_filename)*sizeof(char));
    logger->log_error_path = malloc(strlen(config_manager->log_error_path)*sizeof(char));
    logger->log_error_filename = malloc(strlen(config_manager->log_error_filename)*sizeof(char));
    logger->log_max_size = config_manager->log_max_size*1024*1024;
    
    strcpy(logger->current_error_level, config_manager->log_level);
    strcpy(logger->log_error_path, config_manager->log_error_path);
    strcpy(logger->log_error_filename, config_manager->log_error_filename);
    strcpy(logger->log_verbose_path, config_manager->log_verbose_path);
    strcpy(logger->log_verbose_filename, config_manager->log_verbose_filename);
    
    logger->log_verbose_file_uri = malloc((strlen(logger->log_verbose_path)+strlen(logger->log_verbose_filename)+1)*sizeof(char));
    logger->log_error_file_uri = malloc((strlen(logger->log_error_path)+strlen(logger->log_error_filename)+1)*sizeof(char));
    
    strcat(logger->log_verbose_file_uri, logger->log_verbose_path);
    strcat(logger->log_verbose_file_uri, logger->log_verbose_filename);
    strcat(logger->log_error_file_uri, logger->log_error_path);
    strcat(logger->log_error_file_uri, logger->log_error_filename);
    
    logger->log_error_file_pointer = fopen(logger->log_error_file_uri, "a+");
    logger->log_verbose_file_pointer = fopen(logger->log_verbose_file_uri, "a+");
    
    if (logger->log_error_file_pointer== NULL) {
        fprintf(stderr, "Unable to open error log file \"%s\". Check config file and try again.\n", logger->log_error_file_uri);
        
        exit(EXIT_FAILURE);
    } else if (logger->log_verbose_file_pointer == NULL) {
        fprintf(stderr, "Unable to open verbose log file \"%s\". Check config file and try again.\n", logger->log_verbose_file_uri);
        
        exit(EXIT_FAILURE);
    }
}

void logMessage(char* level_error_message, char* str) {
    if (logger == NULL)
        initLogger();

    char* time_buffer = getCurrentDate(":");
    
    if (strcmp(logger->current_error_level, "VERBOSE") == 0) {
        preProcessLogFile(logger->current_error_level);
        
        if (strcmp(level_error_message, "ERROR") == 0)
            fprintf(logger->log_error_file_pointer, "[%s] %s\n", time_buffer, str);
        else if (strcmp(level_error_message, "VERBOSE"))
            fprintf(logger->log_verbose_file_pointer, "[%s] %s\n", time_buffer, str);
    } else if (strcmp(logger->current_error_level, "ERROR") == 0) {
        preProcessLogFile(logger->current_error_level);
        
        if (strcmp(level_error_message, "ERROR") == 0)
            fprintf(logger->log_error_file_pointer, "[%s] %s\n", time_buffer, str);
    }
    
    free(time_buffer);
}

void preProcessLogFile(char* log_type)
{
    FILE* log_file_pointer;
    char* log_file_uri;
    char* log_file_path;
    char* log_file_name;
    char* time_buffer = getCurrentDate("-");
    
    if (strcmp(log_type, "ERROR") == 0) {
        log_file_uri = logger->log_error_file_uri;
        log_file_path = logger->log_error_path;
        log_file_name = logger->log_error_filename;
        log_file_pointer = logger->log_error_file_pointer;
    } else {
        log_file_uri = logger->log_verbose_file_uri;
        log_file_path = logger->log_verbose_path;
        log_file_name = logger->log_verbose_filename;
        log_file_pointer = logger->log_verbose_file_pointer;
    }
    
    long destination_path_size = strlen(log_file_path)+strlen(log_file_name)+strlen(time_buffer)+1;
    char* destination_path = malloc(destination_path_size*sizeof(char));
    
    float current_log_size = calculateLogDimension(log_file_uri);
    
    strcat(destination_path, log_file_path);
    strcat(destination_path, time_buffer);
    strcat(destination_path, ".");
    strcat(destination_path, log_file_name);

    if (current_log_size >= logger->log_max_size) {
        fprintf(stderr, "Log file size exceeded. Creating new file.\n");
        
        if (!duplicateLogFile(log_file_uri, destination_path))
            fprintf(stderr, "Error during duplication of log file %s.\n", log_file_uri);
        else {
            fclose(log_file_pointer);
            
            log_file_pointer = fopen(log_file_uri, "w+");
        }
    }
    
    free(destination_path);
    free(time_buffer);
}

int duplicateLogFile(char* source_path, char* destination_path)
{
    char ch;
    FILE *source, *target;
    
    source = fopen(source_path, "r");
    
    if(source == NULL) {
        fprintf(stderr, "Error opening source file (%s).\n", source_path);
        
        return 0;
    }
    
    target = fopen(destination_path, "w");
    
    if(target == NULL ) {
        fprintf(stderr, "Error opening destination file (%s).\n", destination_path);
        
        return 0;
    }
    
    while ((ch = fgetc(source)) != EOF )
        fputc(ch, target);
    
    fclose(source);
    fclose(target);
    
    return 1;
}

long calculateLogDimension(char* file_uri)
{
    struct stat stats_of_file;
    
    stat(file_uri, &stats_of_file);
    
    return stats_of_file.st_size;
}

char* getCurrentDate(char* mode)
{
    char* time_buffer = malloc(20*sizeof(char));
    
    time_t current_time = time(NULL);
    struct tm* current_date = localtime(&current_time);
    
    if (strcmp(mode, "-") == 0)
        strftime(time_buffer, 50, "%d-%m-%Y-%H-%M-%S", current_date);
    else
        strftime(time_buffer, 50, "%d-%m-%Y %H:%M:%S", current_date);

    return time_buffer;
}